﻿using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using Zive.Color;

namespace LabColorPicker {

    public partial class ThreeChannelValueEditor: UserControl {

        //
        // Interface
        //

        public ThreeChannelValueEditor( ) {
            IlluminantValue = Illuminants.D65;
            InitializeComponent( );

            _radioButtonMap = new[ ] { Radio1, Radio2, Radio3, };
        }

        // Regular properties

        public ColorSpaceInfo ColorSpace { get; set; }

        public int SelectedIndex {
            get { return _currentChannelIndex; }
            set {
                if ( value < 0 || value > 3 ) {
                    throw new ArgumentOutOfRangeException( "value", value, "Must be 0, 1, 2, or 3." );
                }
                try {
                    foreach ( var radioButton in _radioButtonMap ) {
                        radioButton.IsChecked = false;
                    }
                    if ( value > 0 ) {
                        RadioButton radio = _radioButtonMap[value - 1];
                        radio.IsChecked = true;
                    }
                    _currentChannelIndex = value;
                }
                catch ( Exception ) {
                    throw new ArgumentOutOfRangeException( "value", value, "Must be 0, 1, 2, or 3." );
                }
            }
        }

        // Dependency properties

        public string GroupLabel {
            get { return (string) GetValue( GroupLabelProperty ); }
            set { SetValue( GroupLabelProperty, value ); }
        }

        public string Channel1Label {
            get { return (string) GetValue( Channel1LabelProperty ); }
            set { SetValue( Channel1LabelProperty, value ); }
        }

        public string Channel2Label {
            get { return (string) GetValue( Channel2LabelProperty ); }
            set { SetValue( Channel2LabelProperty, value ); }
        }

        public string Channel3Label {
            get { return (string) GetValue( Channel3LabelProperty ); }
            set { SetValue( Channel3LabelProperty, value ); }
        }

        public string IlluminantLabel {
            get { return (string) GetValue( IlluminantLabelProperty ); }
            set { SetValue( IlluminantLabelProperty, value ); }
        }

        public double Channel1Value {
            get { return (double) GetValue( Channel1ValueProperty ); }
            set { SetValue( Channel1ValueProperty, value ); }
        }

        public double Channel2Value {
            get { return (double) GetValue( Channel2ValueProperty ); }
            set { SetValue( Channel2ValueProperty, value ); }
        }

        public double Channel3Value {
            get { return (double) GetValue( Channel3ValueProperty ); }
            set { SetValue( Channel3ValueProperty, value ); }
        }

        public Illuminants IlluminantValue {
            get { return (Illuminants) GetValue( IlluminantValueProperty ); }
            set { SetValue( IlluminantValueProperty, value ); }
        }

        public int DecimalPlaces {
            get { return (int) GetValue( DecimalPlacesProperty ); }
            set { SetValue( DecimalPlacesProperty, value ); }
        }

        public static readonly DependencyProperty GroupLabelProperty = DependencyProperty.Register( "GroupLabel", typeof( string ), typeof( ThreeChannelValueEditor ) );

        public static readonly DependencyProperty Channel1LabelProperty = DependencyProperty.Register( "Channel1Label", typeof( string ), typeof( ThreeChannelValueEditor ) );
        public static readonly DependencyProperty Channel2LabelProperty = DependencyProperty.Register( "Channel2Label", typeof( string ), typeof( ThreeChannelValueEditor ) );
        public static readonly DependencyProperty Channel3LabelProperty = DependencyProperty.Register( "Channel3Label", typeof( string ), typeof( ThreeChannelValueEditor ) );
        public static readonly DependencyProperty IlluminantLabelProperty = DependencyProperty.Register( "IlluminantLabel", typeof( string ), typeof( ThreeChannelValueEditor ) );

        public static readonly DependencyProperty Channel1ValueProperty = DependencyProperty.Register( "Channel1Value", typeof( double ), typeof( ThreeChannelValueEditor ) );
        public static readonly DependencyProperty Channel2ValueProperty = DependencyProperty.Register( "Channel2Value", typeof( double ), typeof( ThreeChannelValueEditor ) );
        public static readonly DependencyProperty Channel3ValueProperty = DependencyProperty.Register( "Channel3Value", typeof( double ), typeof( ThreeChannelValueEditor ) );
        public static readonly DependencyProperty IlluminantValueProperty = DependencyProperty.Register( "IlluminantValue", typeof( Illuminants ), typeof( ThreeChannelValueEditor ), new PropertyMetadata( Illuminants.D65 ) );

        public static readonly DependencyProperty DecimalPlacesProperty = DependencyProperty.Register( "DecimalPlaces", typeof( int ), typeof( ThreeChannelValueEditor ), new PropertyMetadata( 1 ), DecimalPlaces_ValidateValue );

        // Events

        public event EventHandler Channel1Clicked;
        private void OnChannel1Clicked( ) {
            var handlers = Channel1Clicked;
            if ( null != handlers ) {
                handlers( this, EventArgs.Empty );
            }
        }

        public event EventHandler Channel2Clicked;
        private void OnChannel2Clicked( ) {
            var handlers = Channel2Clicked;
            if ( null != handlers ) {
                handlers( this, EventArgs.Empty );
            }
        }

        public event EventHandler Channel3Clicked;
        private void OnChannel3Clicked( ) {
            var handlers = Channel3Clicked;
            if ( null != handlers ) {
                handlers( this, EventArgs.Empty );
            }
        }

        public event EventHandler Channel1Changed;
        private void OnChannel1Changed( ) {
            var handlers = Channel1Changed;
            if ( null != handlers ) {
                handlers( this, EventArgs.Empty );
            }
        }

        public event EventHandler Channel2Changed;
        private void OnChannel2Changed( ) {
            var handlers = Channel2Changed;
            if ( null != handlers ) {
                handlers( this, EventArgs.Empty );
            }
        }

        public event EventHandler Channel3Changed;
        private void OnChannel3Changed( ) {
            var handlers = Channel3Changed;
            if ( null != handlers ) {
                handlers( this, EventArgs.Empty );
            }
        }

        //
        // Implementation
        //

        // Fields

        private readonly RadioButton[ ] _radioButtonMap;

        private int _currentChannelIndex;

        // Event handlers

        private static bool DecimalPlaces_ValidateValue( object value ) {
            Debug.Print( "ThreeChannelValueEditor.DecimalPlaces_ValidateValue: type={0}, value={1}", value.GetType( ).FullName, value );
            int intval;
            try {
                intval = (int) value;
            }
            catch ( Exception ) {
                return false;
            }
            return ( intval >= 0 && intval <= 18 );
        }

        private void Radio1_Checked( object sender, RoutedEventArgs ev ) {
            Value1.Focus( );
            _currentChannelIndex = 1;
            ev.Source = this;
            OnChannel1Clicked( );
        }

        private void Radio2_Checked( object sender, RoutedEventArgs ev ) {
            Value2.Focus( );
            _currentChannelIndex = 2;
            ev.Source = this;
            OnChannel2Clicked( );
        }

        private void Radio3_Checked( object sender, RoutedEventArgs ev ) {
            Value3.Focus( );
            _currentChannelIndex = 3;
            ev.Source = this;
            OnChannel3Clicked( );
        }

        private void Value1_TextChanged( object sender, TextChangedEventArgs ev ) {
            OnChannel1Changed( );
        }

        private void Value2_TextChanged( object sender, TextChangedEventArgs ev ) {
            OnChannel2Changed( );
        }

        private void Value3_TextChanged( object sender, TextChangedEventArgs ev ) {
            OnChannel3Changed( );
        }

    }

}
